
from myhomework.exceptions.exception import *
from myhomework.models import *
from django.db import models
from myhomework.account.daos import *
import time
import datetime 

'''
Created on 2011-5-12

@author: lchengh2
'''
class HomeworkDao(object):
    
    def __init__(self):
        pass         
            
    @staticmethod            
    def add_homework(homework):
        
        if(homework.id == None ):     
            size = len(Homework.objects.filter(name = homework.name))

        else:
            size = len(Homework.objects.filter(id = homework.id))

        if( size > 0):
            raise HomeworkDuplicationError('')              
        homework.save()
                                   
    @staticmethod    
    def delete_homework_by_name(homework_name):
        
        h = HomeworkDao.get_homework_by_name(homework_name)
        h.delete()

    @staticmethod    
    def delete_homework_by_id(the_homework_id):
        h = HomeworkDao.get_homework_by_id(the_homework_id)
        h.delete()
    
    @staticmethod 
    def update_homework(homework):
        
        if(homework.id <> None):
            size = len(Homework.objects.filter(id = homework.id))
            if(size > 0):
                homework.save()
            else:
                raise HomeworkDoesNotExistError(homework.id)
        else:
            raise HomeworkDoesNotExistError(homework.id)                                        
        
        
    @staticmethod 
    def get_homework_by_name(homework_name):
    
        h = Homework.objects.filter(name = homework_name)
        if(len(h) > 0):
            return h.get()
        else:
            raise HomeworkDoesNotExistError(homework_name)
        
    @staticmethod 
    def get_homework_by_id(id):
        id=int(id)
        h = Homework.objects.filter(id = id)
        if(len(h) > 0):
            return h.get()
        else:
            raise HomeworkDoesNotExistError(id)

        
    @staticmethod 
    def get_homework_list(start, limit):
        
        if ( start < 0 or start >= Homework.objects.all().count() ):
            start = 0
            
        if ( limit < 0 ):
            limit = SettingDao.get_setting('homework_number_per_page')
        
        output_homework_list = Homework.objects.all()[start:start+limit]
        
        return output_homework_list
        
    
    @staticmethod 
    def get_unoverdue_homework_list(start, limit):
        
        if ( start < 0 or start >= Homework.objects.all().count() ):
            start = 0
            
        if ( limit < 0 ):
            limit = SettingDao.get_setting('homework_number_per_page')
        
        now = datetime.datetime.now()
        unoverdue_homework_list = Homework.objects.filter(deadline__gt=now)
    
        output_homework_list = unoverdue_homework_list[start:start+limit]
        
        return output_homework_list
        
    
    @staticmethod 
    def get_overdue_homework_list(start, limit):
        
        if ( start < 0 or start >= Homework.objects.all().count() ):
            start = 0
            
        if ( limit < 0 ):
            limit = SettingDao.get_setting('homework_number_per_page')
        
        now = datetime.datetime.now()
        overdue_homework_list = Homework.objects.filter(deadline__lt=now)
    
        output_homework_list = overdue_homework_list[start:start+limit]
        
        return output_homework_list
    
    @staticmethod 
    def get_homework_count():
        
        count = Homework.objects.all().count()
        
        return count
        
    
    @staticmethod 
    def get_unoverdue_homework_count():
        
        now = datetime.datetime.now()
        unoverdue_homework_list = Homework.objects.filter(deadline__gt=now)
    
        count = unoverdue_homework_list.count()
        
        return count
        
    
    @staticmethod 
    def get_overdue_homework_count():
        
        now = datetime.datetime.now()
        overdue_homework_list = Homework.objects.filter(deadline__lt=now)
    
        count = overdue_homework_list.count()
        
        return count

#print HomeworkDao.get_overdue_homework_count()
     
"""
new_homework = Homework(name='h2',deadline='2011-07-01')
HomeworkDao.add_homework(new_homework)

new_homework = Homework(name='h3',deadline='2011-08-01')
HomeworkDao.add_homework(new_homework)
"""
"""
new_homework = Homework(name='h4',deadline='2011-04-01')
HomeworkDao.add_homework(new_homework)
new_homework = Homework(name='h5',deadline='2011-05-01')
HomeworkDao.add_homework(new_homework)

new_homework = Homework(name='h6',deadline='2011-05-21')
HomeworkDao.add_homework(new_homework)
"""

"""
homework_list = HomeworkDao.get_overdue_homework_list(-100,2)
for homework in homework_list:
    print homework
"""

#now = datetime.datetime.now()
#now = time.localtime()
#print now

"""
now1 = time.time()
print now1

now2 = time.localtime()
timestamp = time.mktime(now2)
 
format="%Y-%m-%d %H:%M:%S" 

timestamp = time.strptime(now1, '%Y-%m-%d %H:%M:%S')
print timestamp
"""

#format="%Y-%m-%d %H:%M:%S"
#t1=time.strptime("2008-01-31 00:11:23",format)
#print t1

#t1=time.strptime(now,format)
#print t1

"""
dateC=datetime.datetime(2010,6,6,8,14,59)
timestamp=time.mktime(dateC.timetuple())
print timestamp
"""

#now_time_list = time.strptime(now)
#print now_time_list 

'''
Created on 2011-5-6

@author: lchengh2
'''
class HomeworkSubmitedDao(object):
    '''
    classdocs
    '''

    def __init__(self):
        '''
        Constructor
        '''

    @staticmethod
    def add_homework_submited(new_homework_submited_info,
                              new_submitter,
                              new_contribution_list = None):
        
        UserDao.get_user_by_student_id(new_submitter.student_id)
        
        if(new_homework_submited_info.id <> None):
            size = len(HomeworkSubmitedInfo.objects.filter(id = new_homework_submited_info.id))
            if(size > 0):
                raise HomeworkSubmitedInfoDuplicationError(new_homework_submited_info.id)

        homework_type = new_homework_submited_info.homework.type
        if(homework_type == 'personal'):
            new_homework_submited_info.save()
            phs = PersonalHomeworkSubmited(homework_submited_info=new_homework_submited_info,
                                           user=new_submitter)
            phs.save()
            
        if(homework_type == 'team'):
                        
            if(new_contribution_list == None):
                raise ContributionsIsNoneError('')
            
            new_homework_submited_info.save()
            new_group = Group.objects.get(id=new_submitter.group_id)            
            ths = TeamworkSubmited(homework_submited_info=new_homework_submited_info,
                                   group=new_group)
            ths.save()
                        
            for c in new_contribution_list:
                c.save()
                ths.contributions.add(c)         
              

    @staticmethod
    def delete_homework_submited(the_homework,
                                 the_submitter):
        
        """
        delete a homework by using value of submitter(User class ) and homework
        """
        the_hs_list = HomeworkSubmitedDao.get_homework_submited_list(the_homework.id, the_submitter.student_id)
        
        for the_hs in the_hs_list:
            the_homework_submited_info = the_hs.homework_submited_info
            if(the_homework.type == 'personal'):
                the_phs = PersonalHomeworkSubmited.objects.filter(homework_submited_info = the_homework_submited_info,
                                                                  user = the_submitter).get()
                the_phs.delete()
            
            if(the_homework.type == 'team'):
                
                if(the_submitter.group == None):
                    return HomeworkSubmitedInfoDoesNotExistError('')
                GroupDao.get_group_by_name(the_submitter.group.name)
                the_ts = TeamworkSubmited.objects.filter(homework_submited_info = the_homework_submited_info,
                                                          group = the_submitter.group).get()
                the_contribution_list = the_ts.contributions.get_query_set().all()
                for c in the_contribution_list:
                    c.delete()
                the_ts.delete()
            the_homework_submited_info.delete()
           
        
    @staticmethod
    def update_homework_submited(new_homework_submited_info):

        """
        update the information of homework submited by using value of homework_submited_info(HomeworkSubmitedInfo)
        """
        
        if(new_homework_submited_info.id == None):
            raise HomeworkSubmitedInfoDoesNotExistError('')
        else:
            size = len(HomeworkSubmitedInfo.objects.filter(id = new_homework_submited_info.id))
            if(size == 0):
                raise HomeworkSubmitedInfoDoesNotExistError('')
            new_homework_submited_info.save()                
        
        
    @staticmethod
    def get_homework_submited(the_homework,
                              the_submitter):

        """
        get the information of homework submitedby using value of submitter (for team homework 
        its value is administrator) and homework
        """
        
        UserDao.get_user_by_student_id(the_submitter.student_id)
        HomeworkDao.get_homework_by_name(the_homework.name)
        
        the_hs_set = HomeworkSubmitedDao.get_homework_submited_list(the_homework.id, 
                                                                    the_submitter.student_id)
        if(len(the_hs_set) > 0):
            result = the_hs_set[0]
        else:
            raise HomeworkSubmitedInfoDoesNotExistError('')                  

        return result         
                
    @staticmethod
    def get_homework_submited_list(the_homework_id,
                                   the_student_id):
        
        '''
        return a list which contains everything about the homework that the student has submitted 
        '''
        
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_submitter = UserDao.get_user_by_student_id(the_student_id)
        result = []
        
        ths_hs_set = HomeworkSubmitedInfo.objects.filter(homework = the_homework).all()

        if(the_homework.type == 'personal'):
            the_phs_set = PersonalHomeworkSubmited.objects.filter(user = the_submitter).all()
            
            result = [phs for phs in the_phs_set for hs in ths_hs_set 
                      if (phs.homework_submited_info == hs)]
                        
        if(the_homework.type == 'team'):
            the_ths_set = TeamworkSubmited.objects.filter(group = the_submitter.group).all()
            
            result = [ths for ths in the_ths_set for hs in ths_hs_set 
                      if (ths.homework_submited_info == hs)]
        
        if(len(result) > 0):        
            result.sort(cmp = HomeworkSubmitedDao.cmp_datetime,reverse=True)
        else:
            result = []
            
        return result

    @staticmethod
    def get_latest_homework_submited_of_group(the_homework_id,
                                              the_group_id):
        
        '''
        return a list ,which includes all the latest homework of a group. 
        '''
        
        the_members = GroupDao.get_group_members_by_group_id(the_group_id)
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        result = []
        if(the_homework.type == 'team'):
            the_admin = GroupDao.get_group_administrator(the_group_id)
            tempList = HomeworkSubmitedDao.get_homework_submited_list(the_homework_id,
                                                                    the_admin.student_id)
            if(len(tempList) > 0):
                result.append(tempList[0])
            
        elif(the_homework.type == 'personal'):
            
            for m in the_members:
                tempList = HomeworkSubmitedDao.get_homework_submited_list(the_homework_id,
                                                                          m.student_id)
                if(len(tempList) > 0):
                    result.append(tempList[0])
                
            result.sort(key=lambda x:x.homework_submited_info.ranking_in_group)
                
        return result
        
    @staticmethod
    def get_latest_homework_submited_of_individual(the_student_id):
        
        '''
        return a list,which includes all the latest homework information of individual about the homework
         '''
        result = []
    
        all_homework = list(Homework.objects.all())

        for h in all_homework:
            the_hs_set = HomeworkSubmitedDao.get_homework_submited_list(h.id, 
                                                                        the_student_id)            
            if(len(the_hs_set) > 0):
                result.append(the_hs_set[0])               

        return result             
    
    @staticmethod
    def get_all_submitted_list(the_student_id,
                               start = None,
                               limit = None):
        '''
        return all homework which the student has submitted
        '''
        
        the_sumbitter = UserDao.get_user_by_student_id(the_student_id)
        result = []
        #personal homework 
        list1 = list(PersonalHomeworkSubmited.objects.filter(user = the_sumbitter).all())
        
        #team work
        the_group = the_sumbitter.group
        if(the_group <> None):          
            list2 = list(TeamworkSubmited.objects.filter(group = the_group).all())
            result = list1 + list2
        else:
            result = list1           
        
        result.sort(cmp = HomeworkSubmitedDao.cmp_datetime,reverse=True)
        
        if((start <> None) and (limit <> None)):
            
            end = start + limit
            if( end > len(result)):
                end = len(result)
            return result[start:end]
        
        return result
    
    @staticmethod
    def get_all_submitted_count(the_student_id):
        result = HomeworkSubmitedDao.get_all_submitted_list(the_student_id)
        return len(result)

    @staticmethod                     
    def get_homework_submited_contributions(the_homework,
                                            the_group):
        """
        get the contribution list of homework submited by using value of group and homework
        """
        
        HomeworkDao.get_homework_by_name(the_homework.name)
        GroupDao.get_group_by_name(the_group.name)
        
        if(the_homework.type == 'personal'):
            raise ContributionsDoesNotExistError('')            
        
        the_hs_set = HomeworkSubmitedInfo.objects.filter(homework=the_homework).all()
        the_ts_set = TeamworkSubmited.objects.filter(group=the_group).all()
        result = None
        for sh in the_hs_set:
            for ts in the_ts_set:
                if(ts.homework_submited_info.id == sh.id):
                    c_set = ts.contributions.get_query_set().all()                  
                    result = c_set
       
        if(result <> None):
            
            return result
        else:
            raise ContributionsDoesNotExistError('')
                
    @staticmethod 
    def update_homework_submited_contributions(the_homework,
                                               the_group,
                                               new_contribution_list):
        
        """
        update the contributions by using value of new_contributions_list and original contributions_set 
        """        
        old_contribution_list = HomeworkSubmitedDao.get_homework_submited_contributions(the_homework, the_group)
        
        for old_c in old_contribution_list:
            for new_c in new_contribution_list:
                if (old_c.user == new_c.user):
                    old_c.contribution = new_c.contribution
                    old_c.save()
    
    @staticmethod           
    def cmp_datetime(hs1,hs2):
        t1 = hs1.homework_submited_info.last_updated_time
        t2 = hs2.homework_submited_info.last_updated_time
        ts1 = time.mktime(t1.timetuple())
        ts2 = time.mktime(t2.timetuple())        
#        print(ts1)
#        print(ts2) 
        if(ts1 > ts2):
            return 1
        if(ts1 < ts2):
            return -1
        return 0              
        
        
'''
Created on 2011-5-12

@author: lchengh2
'''
class AssessmentDao(object):
    def __init__(self):
        pass
    
    @staticmethod
    def sumbmit_teamwork_assessment(the_homework_id,
                                    the_group_id,
                                    the_score):
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_group = GroupDao.get_group_by_id(the_group_id)
        
        am = Assessment(homework = the_homework,
                        group = the_group,
                        highest_score = the_score,
                        lowest_score = the_score)
        AssessmentDao.add_assessment(am)
        
    @staticmethod
    def sumbmit_personal_homework_assessment(the_homework_id,
                                             the_group_id,
                                             the_ranking_check,
                                             the_highest_score,
                                             the_lowest_score):
        
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_group = GroupDao.get_group_by_id(the_group_id)
             
        am = Assessment(homework = the_homework,
                        group = the_group,
                        highest_score = the_highest_score,
                        lowest_score = the_lowest_score,
                        ranking_check = the_ranking_check) 
        AssessmentDao.add_assessment(am)

    @staticmethod
    def add_assessment(the_assessment):
        
        if the_assessment.id <> None:
            size = len(Assessment.objects.filter(id = the_assessment.id).all())
            if(size > 0):
                raise AssessmentDuplicationError(the_assessment.id)                 

        #process others
        the_homework = the_assessment.homework                       
        if the_homework.type == 'team':
            AssessmentDao._update_score_for_teamwork(the_assessment)
        elif the_homework.type == 'personal':
            AssessmentDao._update_score_for_personal_homework(the_assessment)                                         
        the_assessment.save()
            
    
    @staticmethod
    def get_assessment(the_homework_id,
                       the_group_id):
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_group = GroupDao.get_group_by_id(the_group_id)
        the_assessmet = Assessment.objects.filter(homework = the_homework,
                                                  group = the_group).all()           
        if(not the_assessmet):
            raise AssessmentDoesNotExistError(the_group_id)
        return the_assessmet.get()
        
    @staticmethod
    def delete_assessment(the_assessment):
        
        if(the_assessment.id <> None):
            if(not Assessment.objects.filter(id = the_assessment.id).all()):
                raise AssessmentDoesNotExistError(the_assessment.id)
            
            #process others            
            the_homework = the_assessment.homework
            the_group = the_assessment.group
            the_submitter = the_group.administrator 
            if the_homework.type == 'team':
                
                                   
                the_teamwork_submitted = HomeworkSubmitedDao.get_homework_submited(the_homework, 
                                                                                       the_submitter)
                the_homework_submited_info =  the_teamwork_submitted.homework_submited_info
                the_homework_submited_info.score = 0
                HomeworkSubmitedDao.update_homework_submited(the_homework_submited_info)        
                    
            elif the_homework.type == 'personal':
                the_group_members = GroupDao.get_group_members_by_group_id(the_group.id)
                the_homework_submited_list = []#list of phs or ths,not hs_info
                    
                for m in the_group_members:
                    try:
                        temp_hs = HomeworkSubmitedDao.get_homework_submited(the_homework, m)
                        the_homework_submited_list.append(temp_hs)
                    except HomeworkSubmitedInfoDoesNotExistError:
                        pass                 
                    
                for hs in the_homework_submited_list:
                    hs.homework_submited_info.score = 0
                    HomeworkSubmitedDao.update_homework_submited(hs.homework_submited_info)
            the_assessment.delete()                       
        else:
            raise AssessmentDoesNotExistError('')

    @staticmethod
    def update_assessment(the_assessment):
        
        if(the_assessment.id <> None):
      
            if(not Assessment.objects.filter(id = the_assessment.id).all()):
                raise AssessmentDoesNotExistError(the_assessment.id)                
            #process others
            the_homework = the_assessment.homework                       
            if the_homework.type == 'team':
                AssessmentDao._update_score_for_teamwork(the_assessment)
            elif the_homework.type == 'personal':
                    AssessmentDao._update_score_for_personal_homework(the_assessment)                                         
            the_assessment.save()
                           
        else:
            raise AssessmentDoesNotExistError(the_assessment.id)
        
    @staticmethod
    def set_ranking_in_group(the_homework_id,
                             the_group_id,
                             the_id_list):
        
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        if(the_homework.type == 'personal'):
            i = 0
            for id in the_id_list:
                the_user = UserDao.get_user_by_student_id(id)
                try:
                    the_phs = HomeworkSubmitedDao.get_homework_submited(the_homework, 
                                                                        the_user)
                    the_hsi = the_phs.homework_submited_info
                    i += 1
                    the_hsi.ranking_in_group = i
                    HomeworkSubmitedDao.update_homework_submited(the_hsi)
                except:
                    pass

    @staticmethod
    def create_ranking_item(the_user,
                       the_ranking):
        result = {'student_id':the_user.student_id,'ranking':the_ranking}
        return result

    @staticmethod
    def get_personal_homework_performance(the_homework_id,
                                          the_submitter_student_id):    

        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_submitter = UserDao.get_user_by_student_id(the_submitter_student_id)  
        phs = HomeworkSubmitedDao.get_homework_submited(the_homework, the_submitter)    
        hsi = phs.homework_submited_info
        result = {'mark':hsi.score,'rank':hsi.rank,'type':'personal'}
        return result
    
    @staticmethod
    def get_teamwork_performance(the_homework_id,
                                 the_group_id):
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        the_group = GroupDao.get_group_by_id(the_group_id)
        the_admin = the_group.administrator
        ths = HomeworkSubmitedDao.get_homework_submited(the_homework, the_admin)
        hsi = ths.homework_submited_info
        result = {'mark':hsi.score,'rank':hsi.rank,'type':'team'} 
        return result
    
    @staticmethod
    def get_homework_performance(the_homework_id,
                                 the_submitter_student_id):
        
        the_homework = HomeworkDao.get_homework_by_id(the_homework_id)
        result = None
        if the_homework.type == 'team' :
            try:     
                the_user = UserDao.get_user_by_student_id(the_submitter_student_id)
                the_group = the_user.group
                result = AssessmentDao.get_teamwork_performance(the_homework_id,
                                                                the_group.id)
            except HomeworkSubmitedInfoDoesNotExistError:
                pass
                
        elif the_homework.type == 'personal':
            
            try:
                result = AssessmentDao.get_personal_homework_performance(the_homework_id,
                                                                   the_submitter_student_id)
            except HomeworkSubmitedInfoDoesNotExistError:
                pass
        return result
        

    @staticmethod
    def _update_all_ranking_of_homework(the_homework):
        
        hsi_list = list(HomeworkSubmitedInfo.objects.filter(homework = the_homework).order_by('-score'))
        i = 1
        last_score = hsi_list[0].score    
        for hsi in hsi_list:
            if(hsi.score < last_score):
                i += 1
                hsi.rank = i
                last_score = hsi.score                                      
            else:
                hsi.rank = i
            HomeworkSubmitedDao.update_homework_submited(hsi)

    @staticmethod
    def _update_score_for_personal_homework(the_assessment):

        the_homework = the_assessment.homework
        the_group = the_assessment.group
        the_submitter = the_group.administrator         
        
        the_group_members = GroupDao.get_group_members_by_group_id(the_group.id)
        the_homework_submited_list = []#list of phs or ths,not hs_info
        is_lack_homework = False
                
        for m in the_group_members:
            try:
                temp_hs = HomeworkSubmitedDao.get_homework_submited(the_homework, m)
                the_homework_submited_list.append(temp_hs)
            except HomeworkSubmitedInfoDoesNotExistError:
                is_lack_homework = True
                        
        the_homework_submited_list.sort(key=lambda x:x.homework_submited_info.ranking_in_group)
        size = len(the_homework_submited_list)
                               
        if the_assessment.ranking_check :
            the_homework_submited_list[0].homework_submited_info.score = the_assessment.highest_score
            the_homework_submited_list[size -1].homework_submited_info.score = the_assessment.lowest_score
            n = size - 2
            if n <= 0:
                n = 0
                d = 0
            else:
                d = round((the_assessment.highest_score - the_assessment.lowest_score)/(n + 1))
            i = 0
            while i < n :
                the_homework_submited_list[i + 1].homework_submited_info.score = the_homework_submited_list[i].homework_submited_info.score - d
                i += 1
                    
            if(is_lack_homework == False):
                for hs in the_homework_submited_list:
                    if(hs.user == the_submitter):
                        hs.homework_submited_info.score += round(the_assessment.highest_score * 0.1)  
                        if hs.homework_submited_info.score > 100:
                            hs.homework_submited_info.score = 100
                        break
                    
        else:
            for hs in the_homework_submited_list:
                hs.homework_submited_info.score = the_assessment.lowest_score
            for hs in the_homework_submited_list:
                if(hs.user == the_submitter):
                    hs.homework_submited_info.score -= the_assessment.lowest_score * 0.1  
                    if hs.homework_submited_info.score < 0:
                        hs.homework_submited_info.score = 0
                    break                
                
        for hs in the_homework_submited_list:    
            HomeworkSubmitedDao.update_homework_submited(hs.homework_submited_info)
        AssessmentDao._update_all_ranking_of_homework(the_homework)
    
    @staticmethod
    def _update_score_for_teamwork(the_assessment):
        
        the_homework = the_assessment.homework
        the_group = the_assessment.group
        the_submitter = the_group.administrator 
        if (the_assessment.highest_score <> the_assessment.lowest_score) or the_assessment.highest_score == None or the_assessment.lowest_score == None  :
            raise AssessmentScoreValueError('highest_score and lowest_score error')
                               
        the_teamwork_submitted = HomeworkSubmitedDao.get_homework_submited(the_homework, 
                                                                           the_submitter)
        the_homework_submited_info =  the_teamwork_submitted.homework_submited_info
        the_homework_submited_info.score = the_assessment.highest_score
        HomeworkSubmitedDao.update_homework_submited(the_homework_submited_info)
        AssessmentDao._update_all_ranking_of_homework(the_homework)
        
    

class MessageDao(object):
    
    @staticmethod
    def create_message( message ):
        
       pass
   
    @staticmethod
    def delete_message( message ):
        
       pass